package Tests
{
	import Box2D.Collision.Shapes.b2CircleShape;
	import Box2D.Collision.Shapes.b2EdgeShape;
	import Box2D.Collision.Shapes.b2PolygonShape;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.Joints.b2GearJoint;
	import Box2D.Dynamics.Joints.b2GearJointDef;
	import Box2D.Dynamics.Joints.b2PrismaticJoint;
	import Box2D.Dynamics.Joints.b2PrismaticJointDef;
	import Box2D.Dynamics.Joints.b2RevoluteJoint;
	import Box2D.Dynamics.Joints.b2RevoluteJointDef;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2BodyType;
	
	import Framework.Test;
	
	public class Gears extends Test
	{
		private var m_joint1:b2RevoluteJoint;
		private var m_joint2:b2RevoluteJoint;
		private var m_joint3:b2PrismaticJoint;
		private var m_joint4:b2GearJoint;
		private var m_joint5:b2GearJoint;
		public function Gears()
		{
			super();
			createGround();
			createGears();
		}
		private function createGround():void{
			var shape:b2EdgeShape = new b2EdgeShape;
			shape.Set(new b2Vec2(-50,0),new b2Vec2(50,0));
			m_groundBody.CreateFixtureByShape(shape,0);
		}
		private function createGears():void{
			var circle1:b2CircleShape = new b2CircleShape;
			circle1.radius = 1.0;
			
			var circle2:b2CircleShape = new b2CircleShape;
			circle2.radius = 2.0;
			
			var box:b2PolygonShape = new b2PolygonShape;
			box.SetAsBox(0.5, 5.0);
			
			var bd1:b2BodyDef = new b2BodyDef;
			bd1.type = b2BodyType.b2_dynamicBody;
			bd1.position.Set(-3.0, 12.0);
			var body1:b2Body = m_world.CreateBody(bd1);
			body1.CreateFixtureByShape(circle1, 5.0);
			
			var jd1:b2RevoluteJointDef = new b2RevoluteJointDef;
			jd1.bodyA = m_groundBody
			jd1.bodyB = body1;
			jd1.localAnchorA = m_groundBody.GetLocalPoint(bd1.position);
			jd1.localAnchorB = body1.GetLocalPoint(bd1.position);
			jd1.referenceAngle = body1.GetAngle() - m_groundBody.GetAngle();
			m_joint1 = m_world.CreateJoint(jd1) as b2RevoluteJoint;
			
			var bd2:b2BodyDef = new b2BodyDef;
			bd2.type = b2BodyType.b2_dynamicBody;
			bd2.position.Set(0.0, 12.0);
			var body2:b2Body = m_world.CreateBody(bd2);
			body2.CreateFixtureByShape(circle2, 5.0);
			
			var jd2:b2RevoluteJointDef = new b2RevoluteJointDef;
			jd2.Initialize(m_groundBody, body2, bd2.position);
			m_joint2 = m_world.CreateJoint(jd2) as b2RevoluteJoint;
			 
			var bd3:b2BodyDef = new b2BodyDef;
			bd3.type = b2BodyType.b2_dynamicBody;
			bd3.position.Set(2.5, 12.0);
			var body3:b2Body = m_world.CreateBody(bd3);
			body3.CreateFixtureByShape(box, 5.0);
			
			var jd3:b2PrismaticJointDef = new b2PrismaticJointDef;
			jd3.Initialize(m_groundBody, body3, bd3.position, new b2Vec2(0.0, 1.0));
			jd3.lowerTranslation = -5.0;
			jd3.upperTranslation = 5.0;
			jd3.enableLimit = true;
			
			m_joint3 = m_world.CreateJoint(jd3) as b2PrismaticJoint;
			
			var jd4:b2GearJointDef = new b2GearJointDef;
			jd4.bodyA = body1;
			jd4.bodyB = body2;
			jd4.joint1 = m_joint1;
			jd4.joint2 = m_joint2;
			jd4.ratio = circle2.radius / circle1.radius;
			m_joint4 = m_world.CreateJoint(jd4) as b2GearJoint;
			
			var jd5:b2GearJointDef = new b2GearJointDef;
			jd5.bodyA = body2;
			jd5.bodyB = body3;
			jd5.joint1 = m_joint2;
			jd5.joint2 = m_joint3;
			jd5.ratio = -1.0 / circle2.radius;
			m_joint5 = m_world.CreateJoint(jd5) as b2GearJoint;	
		}
		public override function Step():void{
			super.Step();
			
			var ratio:Number;
			var value:Number;
			var msg:String;
			
			ratio = m_joint4.GetRatio();
			value = m_joint1.GetJointAngle() + ratio * m_joint2.GetJointAngle();
			msg = 'theta1 + ' + ratio.toFixed(2) + ' * theta2 = ' + value.toFixed(2);
			writeMessage(msg);
			
			ratio = m_joint5.GetRatio();
			value = m_joint2.GetJointAngle() + ratio * m_joint3.GetJointTranslation();
			msg = 'theta2 + ' + ratio.toFixed(2) + ' * delta = ' + value.toFixed(2);
			writeMessage(msg);
		}
	}
}